﻿using System;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Text;
using UnityEngine;

namespace GameClient
{
    public class NetIO
    {
        string connect="127.0.0.1";//连接字符串
        int port = 666;//端口
        Socket socket;
        bool reading = false, writing = false;
        byte[] data = new byte[1024];
        List<byte> cache = new List<byte>();//缓存区
        Queue<TransModel> wqueue=new Queue<TransModel>();//模型队列
        public List<TransModel> models = new List<TransModel>();//传输模型列表
        private static NetIO Instance;
        public static NetIO instance
        {
            get {
                if(Instance==null)
                Instance=new NetIO();
                return Instance;
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="con">连接字符串</param>
        /// <param name="p">端口</param>
        public NetIO()
        {
            start();
        }
        void start()
        {
            try
            {
                socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                socket.Connect(connect, port);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
            try
            {
                socket.BeginReceive(data, 0, data.Length, SocketFlags.None, ReceiveCallBack, null);
            }
            catch (Exception ex)
            {
                socket.Shutdown(SocketShutdown.Both);
                socket.Close();
            }
        }
        void ReceiveCallBack(IAsyncResult ar)
        {
            int length = socket.EndReceive(ar);
            if (length > 0)
            {
                //处理消息
                byte[] value = new byte[length];
                Buffer.BlockCopy(data, 0, value, 0, length);
                cache.AddRange(value);
                if (!reading)
                {
                    reading = true;
                    read();
                }
                try
                {
                    //循环接受消息
                    socket.BeginReceive(data, 0, data.Length, SocketFlags.None, ReceiveCallBack, null);
                }
                catch (Exception ex)
                {
                    socket.Shutdown(SocketShutdown.Both);
                    socket.Close();
                    Console.WriteLine(ex.ToString());
                }
            }
        }
        public void read()
        {
            byte[] result = Lengthcode.LengthDeCode(ref cache);
            if (result == null)
            {
                reading = false;
                return;
            }
            //传输模型解码
            else
            {
                TransModel model = TransModelCode.TransModelDeCode(result);
                if (model == null)
                {
                    reading = false;
                    return;
                }
                //通知上层应用有消息到达，准备处理model
                models.Add(model);
                //Console.WriteLine("{0},,{1},,{2},,{3}",model.type,model.area,model.command,model.GetMessage<string>());
                read();//进行递归，继续读取消息
            }
        }
        /// <summary>
        /// 发送模型
        /// </summary>
        public void send(TransModel model)
        {
            wqueue.Enqueue(model);
            if (!writing)
            {
                writing = true;
                write();
            }
        }
        public void write()
        {
            if (wqueue.Count <= 0)
            {
                writing = false;
                return;
            }
            TransModel model = wqueue.Dequeue();
            byte[] result = TransModelCode.TransModelECode(model);//传输模型编码
            if (result == null || result.Length <= 0)
            {
                writing = false;
                return;
            }
            byte[] re = Lengthcode.LengthECode(result);//长度编码
            //args_write.SetBuffer(re, 0, re.Length);//设置写入异步套接字的缓冲区

            try
            {
                //bool v = socket.SendAsync(args_write);//判断是否挂起
                //if (!v)
                //{
                //    send_de(args_write);
                //}
                socket.BeginSend(re,0,re.Length,SocketFlags.None,SendCallBack,null);
            }
            catch (Exception ex)
            {
                Debug.Log(ex.ToString());
            }
        }
        void SendCallBack(IAsyncResult ar)
        {
            socket.EndSend(ar);
            write();//写消息循环
        }

    }
}